#if defined(_MSC_VER)
#pragma once
#endif

#ifndef LM_CORE_SHAPE_H
#define LM_CORE_SHAPE_H

#include "lm.h"
#include "memory.h"
#include "intersection.h"
#include "material.h"
#include "transform.h"

class Shape : public ReferenceCounted {
public:
	// Shape Interface
	Shape(const Transform *o2w, const Transform *w2o, bool ro, Reference<Material> mat);
	virtual ~Shape();
	virtual BBox ObjectBound() const = 0;
	virtual BBox WorldBound() const;
	virtual bool CanIntersect() const {
		return true;
	}
	virtual void Refine(vector<Reference<Shape>> &refined) const { }
	// Modify ray.tmax
	virtual bool Intersect(const Ray &ray, Intersection *isect) const;
	// Donot modify ray.tmax
	virtual bool IntersectP(const Ray &ray) const;
	// Fill information in Intersection
	virtual void FillIntersection(const Ray &ray, Intersection *isect) const;
	virtual BSDF *GetBSDF(const Intersection &isect) const;
	virtual void GetShadingGeometry(const Intersection &isect) const {
		// Allow shape to modify intersection, if necess.
		// Call before use material to get BSDF..
		// Do nothing default.
		// isect.shadingFrame = isect.geometryFrame
	}
	virtual void SetLight(AreaLight *light) {
		arealight = light;
	}
	virtual float Area() const;
	virtual Point3 Sample(const Point2 &sample, Normal *Ns) const {
		Fatal("Unimplemented Shape::Sample() method called");
        return Point3();
	}
	virtual float Pdf(const Point3 &Pshape) const {
        return 1.f / Area();
    }
    virtual Point3 Sample(const Point3 &p, const Point2 &sample,
                         Normal *Ns) const {
        return Sample(sample, Ns);
    }
    virtual float Pdf(const Point3 &p, const Vector3 &wi) const;

	// for openGL
	virtual void RenderGL(bool textured = false) const { }
	// Public data
	const Transform *ObjectToWorld, *WorldToObject;
	const bool ReverseOrientation, TransformSwapsHandedness;
	const uint32_t shapeId;
	static uint32_t nextshapeId;
	Reference<Material> material;
	AreaLight *arealight;
};

#endif	// LM_CORE_SHAPE_H
